#include "Weapon.h"
#include "Bullet.h"
#include "GameManager.h"
#include "ShootEmUp.h"
#include "MainCharacter.h"

using namespace Ogre;
using namespace std;

int Weapon::ID=0;
const char* Weapon::DEFAULT_NAME="weapon_";
const char* Weapon::DEFAULT_NODE_NAME="WeaponNode";

Weapon::Weapon(WeaponType _type, WeaponLevel _level)
: Item(Weapon::DEFAULT_NAME + StringConverter::toString(Weapon::ID)),
mTimeUntilDestruction(0),
type(_type),
level(_level)
{
	Weapon::ID++;
	mSceneMgr = ShootEmUp::getSingleton().getSceneManager();
	initialize();
}

Weapon::~Weapon()
{}

void Weapon::initialize()
{
	repetitionTime = 0.1f;
	mTimeUntilDestruction = Ogre::Math::RangeRandom(3.0f, 15.0f);
	if ( type != BUG )
	{
		mEntity = mSceneMgr->createEntity(getName(), "bonusWeapon.mesh");
		mEntity->setUserObject( this );
		mSceneNode = mSceneMgr->getSceneNode(Bonus::DEFAULT_NODE_NAME)->createChildSceneNode(Bonus::DEFAULT_NODE_NAME+string("_")+getName());
		Vector3 initialPosition( 
			Math::RangeRandom(ShootEmUp::WORLD_MIN.x, ShootEmUp::WORLD_MAX.x), 
			Math::RangeRandom(ShootEmUp::WORLD_MIN.y, ShootEmUp::WORLD_MAX.y), 
			ShootEmUp::WORLD_MAX.z
			);
		mSceneNode->setPosition( initialPosition );
		mSceneNode->scale( Vector3::UNIT_SCALE * 0.4 );
		mSceneNode->attachObject( mEntity );
	}
}

Bullet* Weapon::createBullet(const Ogre::Vector3& startPosition)
{
	Entity* bulletEntity = 0;
	Bullet* bullet = 0;
	Vector3 scalefactor(Vector3::UNIT_SCALE);
	if ( unusedBullets.size() < 3 )
	{
		string bulletMesh;
		switch(type)
		{
		case SNOW:
			bulletMesh = "boulle.mesh";
			repetitionTime = 0.4f;
			scalefactor = Vector3::UNIT_SCALE * 0.6f;
			break;
		case ICE:
			bulletMesh = "pic.mesh";
			repetitionTime = 0.3f;
			scalefactor = Vector3(0.6f, 1.6f, 0.6f);
			break;
		case WATER:
			bulletMesh = "jet.mesh";
			repetitionTime = 0.2f;
			scalefactor = Vector3(1.0f, 6.f, 1.0f);
			break;
		case BUG:
			bulletMesh = "bug.mesh";
			scalefactor = Vector3::UNIT_SCALE * 0.6f;
			break;
		}
		string bulletName = Bullet::DEFAULT_NAME + StringConverter::toString(Bullet::ID);
		bulletEntity = mSceneMgr->createEntity(bulletName, bulletMesh);
		bullet = new Bullet(this, bulletEntity, startPosition);
		bullet->getSceneNode()->scale( scalefactor );
		if ( level == LEVEL2 )
		{
			bulletName = Bullet::DEFAULT_NAME + StringConverter::toString(Bullet::ID);
			bulletEntity = mSceneMgr->createEntity(bulletName, bulletMesh);
			Bullet* bullet0 = new Bullet(this, bulletEntity, startPosition - Vector3(-45.0, 0, 0));
			bullet0->getSceneNode()->scale( scalefactor );
			Ogre::Root::getSingleton().addFrameListener( bullet0 );

			bulletName = Bullet::DEFAULT_NAME + StringConverter::toString(Bullet::ID);
			bulletEntity = mSceneMgr->createEntity(bulletName, bulletMesh);
			Bullet* bullet2 = new Bullet(this, bulletEntity, startPosition - Vector3(45.0, 0, 0));	
			bullet2->getSceneNode()->scale( scalefactor );
			Ogre::Root::getSingleton().addFrameListener( bullet2 );
		}
	}
	else
	{
		bullet = unusedBullets.back();
		unusedBullets.pop_back();
		bullet->reset(startPosition);
		if ( level == LEVEL2 )
		{
			Bullet* bullet0 = unusedBullets.back();
			unusedBullets.pop_back();
			bullet0->reset( startPosition - Vector3(-45.0, 0, 0) );
			Ogre::Root::getSingleton().addFrameListener( bullet0 );

			Bullet* bullet2 = unusedBullets.back();
			unusedBullets.pop_back();
			bullet2->reset( startPosition - Vector3(45.0, 0, 0) );
			Ogre::Root::getSingleton().addFrameListener( bullet2 );
		}
	}
	Ogre::Root::getSingleton().addFrameListener( bullet );
	return bullet;
}

void Weapon::destroyBullet(Bullet* bullet)
{
	Ogre::Root::getSingleton().removeFrameListener( bullet );
	unusedBullets.push_back( bullet );
	bullet->getSceneNode()->detachObject( bullet->getEntity() );
}

void Weapon::collision(Item * _item)
{
	_item->collisionWithWeapon( this );
}

void Weapon::collisionWithBullet(Bullet *)
{}

void Weapon::collisionWithEnemy(Enemy *)
{}

void Weapon::collisionWithMainCharacter(MainCharacter * maincharacter)
{
	maincharacter->collisionWithWeapon( this );
}

void Weapon::collisionWithFish(Fish * _fish)
{}

void Weapon::collisionWithBonus(Bonus* _bonus)
{}

void Weapon::collisionWithWeapon(Weapon* weapon)
{}

bool Weapon::frameStarted(const FrameEvent& evt)
{
	if (mTimeUntilDestruction >= 0)
		mTimeUntilDestruction -= evt.timeSinceLastFrame;
	else
	{
		GameManager::getSingleton().destroyWeapon( this );
	}
	return true;
}
